package com.javastudy.autowiredStudy.scopetest;

import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 自定义scope
 *  假设：目的是要实现同一个线程从ioc中获取的是同一个bean
 * @author mac
 * @date 2021/9/7 11:28 上午
 */
public class ZidingyiScope {
}

/**
 * 第一步 实现scope接口写入实现逻辑
 */
class ScopeClass implements Scope{
    private  ThreadLocal THREAD_SCOPE = new ThreadLocal();
    volatile AtomicInteger i = new AtomicInteger();
    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        Object o = THREAD_SCOPE.get();
        int i = this.i.addAndGet(1);
        System.out.println("i = " + this.i);
        if (o != null) {
            return o;
        }
        Object object = objectFactory.getObject();
        THREAD_SCOPE.set(object);
        return object;
    }

    @Override
    public Object remove(String name) {
        THREAD_SCOPE.remove();
        return null;
    }

    @Override
    public void registerDestructionCallback(String name, Runnable callback) {

    }

    @Override
    public Object resolveContextualObject(String key) {
        return null;
    }

    @Override
    public String getConversationId() {
        return null;
    }
}

/**
 * 将这个实现类添加到ioc容器
 */
@Component
class ScopeClassBeanFactoryPostProcess implements BeanFactoryPostProcessor{
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.registerScope("thradScope",new ScopeClass());
    }
}

/**
 * 第三步 使用这个scope
 */
@org.springframework.context.annotation.Scope("thradScope")
@Service
class ScopeOperationClass{
    public void aa(){}
}